package MazeGenProject;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.*;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jhotdraw.framework.Figure;
import org.jhotdraw.framework.FigureEnumeration;
import org.jhotdraw.framework.HandleEnumeration;
import org.jhotdraw.standard.AbstractFigure;
import org.jhotdraw.standard.CompositeFigure;
import org.jhotdraw.standard.HandleEnumerator;
import org.jhotdraw.standard.RelativeLocator;
import org.jhotdraw.util.CollectionsFactory;

public class RandomMaze extends CompositeFigure
{
	private Room[][] rooms; //2D array of rooms
	private ArrayList<Wall> walls; //List of walls
	private Random rand;
	private int height;
	private int width;
	private int num;
	private JoinRoom ds;

	private int xCoordinate; 
	private int yCoordinate;
	private int roomSize;
	private int randomWall;

	private GridDrawing gridDrawing;
	
	public RandomMaze(GridDrawing d, int height, int width) 
	{
		gridDrawing = d;
		
		this.height = height;
		this.width = width;
		rooms = new Room[height][width];
		walls = new ArrayList<Wall>((height - 1) * (width - 1));
		generateRandomMaze();
		drawRooms();
	}
	
	private void generateRandomMaze() 
	{
		generateInitialRooms();
		ds = new JoinRoom(width * height);
		rand = new Random();
		num = width * height;

		while (num > 1) 
		{
			//Pick a random wall we want- avoid removing border
			randomWall = rand.nextInt(walls.size());
			Wall temp = walls.get(randomWall);
			//Choose two rooms randomly
			int roomA = temp.currentRoom.y + temp.currentRoom.x * width;
			int roomB = temp.nextRoom.y + temp.nextRoom.x * width;

			//Check if rooms already joined
			if (ds.find(roomA) != ds.find(roomB)) 
			{
				walls.remove(randomWall);
				ds.unionRooms(ds.find(roomA), ds.find(roomB));
				temp.isGone = true;
				temp.currentRoom.adj.add(temp.nextRoom);
				temp.nextRoom.adj.add(temp.currentRoom);
				num--;
			}
		}
	}

	
	private int roomNumber = 0;

	//Creates initial maze filled with singular rooms
	private void generateInitialRooms() 
	{
		for (int i = 0; i < height; i++) 
		{
			for (int j = 0; j < width; j++) 
			{
				//Create north wall
				rooms[i][j] = new Room(i, j);
				if (i == 0) 
				{
					rooms[i][j].north = new Wall(rooms[i][j]);
				} 
				else 
				{
					rooms[i][j].north = new Wall(rooms[i - 1][j], rooms[i][j]);
					walls.add(rooms[i][j].north);
				}
				if (i == height - 1) 
				{
					rooms[i][j].south = new Wall(rooms[i][j]);
				}
				if (j == 0) 
				{
					rooms[i][j].west = new Wall(rooms[i][j]);
				} 
				else 
				{
					rooms[i][j].west = new Wall(rooms[i][j - 1], rooms[i][j]);
					walls.add(rooms[i][j].west);
				}
				if (j == width - 1) 
				{
					rooms[i][j].east = new Wall(rooms[i][j]);
				}
				//Name rooms
				rooms[i][j].roomName = roomNumber++;
			}
		}
		//Create entrance and exit
		//Remove west wall of room 0
		rooms[0][0].west.isGone = true;
		//Top left room named 0
		rooms[0][0].roomName = 0;
		//Remove south wall of last room
		rooms[height - 1][width - 1].east.isGone = true;

		rooms[height - 1][width - 1].roomName = (height * width);
	}
	
	public void drawRooms() 
	{
		xCoordinate = 20;
		yCoordinate = 20;
		
		//Pixel size of room- rooms are 20x20 pixels
		roomSize = 20;

		int x = xCoordinate;
		int y = yCoordinate;

		for (int i = 0; i <= height - 1; i++) 
		{
			for (int j = 0; j <= width - 1; j++) 
			{
				if (!(rooms[i][j].north.isGone)) 
				{
					//g.drawLine(x, y, x + roomSize, y);
					add(new WallFigure(gridDrawing, x, y, x + roomSize, y));
				}
				if (rooms[i][j].west.isGone == false) 
				{
					//g.drawLine(x, y, x, y + roomSize);
					add(new WallFigure(gridDrawing, x, y, x, y + roomSize));
				}
				if ((i == height - 1) && rooms[i][j].south.isGone == false) 
				{
					//g.drawLine(x, y + roomSize, x + roomSize, y + roomSize);
					add(new WallFigure(gridDrawing, x, y + roomSize, x + roomSize, y + roomSize));
				}
				if ((j == width - 1) && rooms[i][j].east.isGone == false) 
				{
					//g.drawLine(x + roomSize, y, x + roomSize, y + roomSize);
					add(new WallFigure(gridDrawing, x + roomSize, y, x + roomSize, y + roomSize));
				}
				x += roomSize;
			}
			x = xCoordinate;
			y += roomSize;
		}
	}

	@Override
	public void basicDisplayBox(Point origin, Point corner) 
	{
		
	}

	@Override
	public Rectangle displayBox() 
	{
		FigureEnumeration fe = figures();
		Rectangle r = fe.nextFigure().displayBox();

		while (fe.hasNextFigure()) 
		{
			r.add(fe.nextFigure().displayBox());
		}
		return r;
	}

	@Override
	public HandleEnumeration handles() 
	{
		List handles = CollectionsFactory.current().createList();
		handles.add(new GroupHandle(this, RelativeLocator.northWest()));
		handles.add(new GroupHandle(this, RelativeLocator.northEast()));
		handles.add(new GroupHandle(this, RelativeLocator.southWest()));
		handles.add(new GroupHandle(this, RelativeLocator.southEast()));
		return new HandleEnumerator(handles);
	}
	
	public Room[][] getRooms()
	{
		return rooms;
	}

//	public static void main(String[] args) 
//	{
//		JFrame frame = new JFrame();
//		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//		frame.setSize(500, 800);
//		frame.getContentPane().add(new RandomMaze(20, 20));
//		frame.pack();
//		frame.setVisible(true);
//	}
}